<template><div><p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="facades" tabindex="-1"><a class="header-anchor" href="#facades"><span>Facades</span></a></h2>
<ul>
<li><a href="#introduction">介绍</a></li>
<li><a href="#when-to-use-facades">何时使用 Facades</a>
<ul>
<li><a href="#facades-vs-dependency-injection">Facades vs 依赖注入</a></li>
<li><a href="#facades-vs-helper-functions">Facades vs 辅助函数</a></li>
</ul>
</li>
<li><a href="#how-facades-work">Facades 原理</a></li>
<li><a href="#real-time-facades">实时 Facades</a></li>
<li><a href="#facade-class-reference">Facade 类引用</a></li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p>贯穿整个 Laravel 文档, 可以看到许多通过 Facades 与 Laravel 功能交互的代码示例。Facades 为应用 <a href="https://learnku.com/docs/laravel/11.x/container" target="_blank" rel="noopener noreferrer">服务容器</a> 中的类提供「静态」接口。 并且 Laravel 自带了许多 Facades, 它们几乎可以调用到 Laravel 中所有的功能。</p>
<p>Laravel Facades 充当服务容器中底层类的「静态代理」,提供简洁、富有表现力的语法的优点, 同时保持比传统静态方法更高的可测试性和灵活性。如果你不完全理解 Facades 是如何工作的, 那也没关系 - 只需正常学习 Laravel 即可, 后面自然而然就会明白了。</p>
<p>Laravel 的所有 Facades 都定义在 <code v-pre>Illuminate\Support\Facades</code> 命名空间。可以像这样访问 Facades：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Route</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="辅助函数" tabindex="-1"><a class="header-anchor" href="#辅助函数"><span>辅助函数</span></a></h4>
<p>为了补充 Facades 能力, Laravel 提供了全局「辅助函数」, 和常见一些功能交互变得更加容易, 常见辅助函数有 <code v-pre>view</code> 、<code v-pre>response</code> 、<code v-pre>url</code> 、<code v-pre>config</code> 等。 Laravel 提供的每个辅助函数都有其相应作用；<a href="https://learnku.com/docs/laravel/11.x/helpers" target="_blank" rel="noopener noreferrer">帮助文档</a> 提供了完整的列表可供查看所有辅助函数。</p>
<p>例如，可以使用 <code v-pre>response</code> 函数，而不是使用 <code v-pre>Illuminate\Support\Facades\Response</code> Facade 来生成 JSON 响应。辅助函数是全局可用的，无需导入任何类即可使用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Response</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/users'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">Response</span><span class="token operator">::</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token comment">// ...</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/users'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">response</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">            <span class="token comment">// ...</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="何时使用-facades" tabindex="-1"><a class="header-anchor" href="#何时使用-facades"><span>何时使用 Facades</span></a></h2>
<p>Facades 提供了简洁、易于记忆的语法, 无需记住要手动注入或配置的长类名。此外，由于它是 PHP 动态调用的, 很容易测试。</p>
<p>然而，在使用 Facades 时必须小心。它的主要危险是类的「作用范围扩张」。Facades 的易于使用且不需要注入, 这就导致在类的持续开发过程中, 很容易不知不觉用到许多的 Facades。使用依赖注入时, 这种潜在问题通过构造函数变得更为明显，类慢慢变得越来越大。所以，在使用 Facades 时，需要特别关注类的大小, 以便它保持责任范围单一, 如果类变得太大, 请考虑将它拆分成多个较小的类。</p>
<h3 id="facades-vs-依赖注入" tabindex="-1"><a class="header-anchor" href="#facades-vs-依赖注入"><span>Facades vs. 依赖注入</span></a></h3>
<p>依赖注入的主要好处之一是能够交换注入类的实现。这在测试时非常有用，可以注入 mock 或 stub，并断言在 stub 上调用了各种方法。</p>
<p>通常，无法 mock 或 stub 一个真正的静态类方法。但是, 由于 Laravel 的 Facades 使用动态方法来代理对从服务容器中解析出来的对象的方法调用, 实际上可以像测试注入的类实例一样测试 Facades。例如，给定以下路由：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>使用 Laravel 的 Facade 测试方法，可以编写以下测试来验证 <code v-pre>Cache::get</code> 方法是否如期望的参数被调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// Pest</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">test</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'basic example'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">shouldReceive</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'get'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">andReturn</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token comment">// PHPUnit</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 一个简单的功能测试示例</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">test_basic_example</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">shouldReceive</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'get'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span></span>
<span class="line">         <span class="token operator">-></span><span class="token function">andReturn</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="facades-vs-辅助函数" tabindex="-1"><a class="header-anchor" href="#facades-vs-辅助函数"><span>Facades vs. 辅助函数</span></a></h3>
<p>除了 Facades，Laravel 还包含许多 「辅助」函数，这些函数可以执行常见的任务，如生成视图、触发事件、调度任务或发送 HTTP 响应。许多这些辅助函数与对应的 Facades 执行相同的功能。例如，以下 Facade 调用和辅助函数调用是等效的：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">return</span> <span class="token class-name class-name-fully-qualified static-context">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>View</span><span class="token operator">::</span><span class="token function">make</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'profile'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">view</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'profile'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Facades 和辅助函数在实际上没有任何区别。当使用辅助函数时，仍然可以像测试对应的 Facade 那样来测试它们。例如，给定以下路由：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"></span>
<span class="line">    <span class="token class-name static-context">Route</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">cache</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code v-pre>cache</code> 辅助函数会调用 <code v-pre>Cache</code> Facade 底层类的 <code v-pre>get</code> 方法。因此, 即使使用的是辅助函数, 也可以用下面的测试来验证该方法是否如期望的参数被调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 一个简单的功能测试示例。</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">test_basic_example</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">shouldReceive</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'get'</span><span class="token punctuation">)</span></span>
<span class="line">             <span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'key'</span><span class="token punctuation">)</span></span>
<span class="line">             <span class="token operator">-></span><span class="token function">andReturn</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$response</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$response</span><span class="token operator">-></span><span class="token function">assertSee</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="facades-原理" tabindex="-1"><a class="header-anchor" href="#facades-原理"><span>Facades 原理</span></a></h2>
<p>在 Laravel 应用中, Facade 是一个类, 它提供了对容器中对象的访问。使这一切工作的机制位于 <code v-pre>Facade</code> 类中。Laravel 的 Facades, 以及你创建的任何自定义 Facades, 都将扩展基础的 <code v-pre>Illuminate\Support\Facades\Facade</code> 类。</p>
<p><code v-pre>Facade</code> 基础类使用 <code v-pre>__callStatic()</code> 魔术方法来将 Facade 上的调用委托给从容器中解析出来的对象。在下面的例子中, 对 Laravel 缓存系统的调用被做出了。通过查看这段代码, 你可能会认为 <code v-pre>Cache</code> 类上的静态 <code v-pre>get</code> 方法被调用了：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Controllers<span class="token punctuation">\</span>Controller</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Support<span class="token punctuation">\</span>Facades<span class="token punctuation">\</span>Cache</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>View<span class="token punctuation">\</span>View</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">class</span> <span class="token class-name-definition class-name">UserController</span> <span class="token keyword">extends</span> <span class="token class-name">Controller</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token doc-comment comment">/**</span>
<span class="line">         * 显示给定用户的个人资料。</span>
<span class="line">         */</span></span>
<span class="line">        <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">showProfile</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">View</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$user</span> <span class="token operator">=</span> <span class="token class-name static-context">Cache</span><span class="token operator">::</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'user:'</span><span class="token operator">.</span><span class="token variable">$id</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">            <span class="token keyword">return</span> <span class="token function">view</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'profile'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'user'</span> <span class="token operator">=></span> <span class="token variable">$user</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>注意观察上面的代码, 在顶部 「导入」了 <code v-pre>Cache</code> Facade。这个 Facade 作为代理来访问 <code v-pre>Illuminate\Contracts\Cache\Factory</code> 接口的底层实现。使用 Facade 进行的任何调用都将传递给底层实例的相应方法。由于 Facade 使用了 Laravel 的服务容器来解析这些对象, 因此可以轻松地在容器中模拟或替换这些对象以进行测试。</p>
<p>如果查看 <code v-pre>Illuminate\Support\Facades\Cache</code> 类, 就会发现并没有静态方法 <code v-pre>get</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token keyword">class</span> <span class="token class-name-definition class-name">Cache</span> <span class="token keyword">extends</span> <span class="token class-name">Facade</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token doc-comment comment">/**</span>
<span class="line">         * Get the registered name of the component.</span>
<span class="line">         */</span></span>
<span class="line">        <span class="token keyword">protected</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function-definition function">getFacadeAccessor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">string</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">return</span> <span class="token string single-quoted-string">'cache'</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>相反, <code v-pre>Cache</code> Facade 继承自基础的 <code v-pre>Facade</code> 类, 并定义了 <code v-pre>getFacadeAccessor()</code> 方法。这个方法的职责是返回服务容器绑定的名称。当用户引用 <code v-pre>Cache</code> Facade 上的任何静态方法时，Laravel 会从<a href="https://learnku.com/docs/laravel/11.x/container" target="_blank" rel="noopener noreferrer">服务容器</a>中解析出 <code v-pre>cache</code> 绑定，并在那个对象上运行请求的方法（在本例中为 <code v-pre>get</code>）。</p>
<h2 id="实时-facades" tabindex="-1"><a class="header-anchor" href="#实时-facades"><span>实时 Facades</span></a></h2>
<p>使用实时 Facades, 可以将应用程序中的任何类当作 Facade 来处理。为了说明这如何被使用, 首先查看一些没有使用实时 Facades 的代码。例如, 假设 <code v-pre>Podcast</code> 模型有一个 <code v-pre>publish</code> 方法。但是, 为了发布播客, 需要注入一个 <code v-pre>Publisher</code> 实例：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Publisher</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">class</span> <span class="token class-name-definition class-name">Podcast</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token doc-comment comment">/**</span>
<span class="line">         * 发布播客。</span>
<span class="line">         */</span></span>
<span class="line">        <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">publish</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Publisher</span> <span class="token variable">$publisher</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'publishing'</span> <span class="token operator">=></span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">            <span class="token variable">$publisher</span><span class="token operator">-></span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>将发布者实现注入方法中可以让我们轻松地隔离测试该方法，因为我们可以模拟被注入的发布者。然而，它要求我们每次调用 <code v-pre>publish</code> 方法时总是传递一个发布者实例。使用实时 Facades，我们可以在不需要显式传递 Publisher 实例的情况下保持相同的可测试性。为了生成一个实时 facade，将导入类的命名空间前缀加上 Facades：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">    <span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Models</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Publisher</span><span class="token punctuation">;</span> <span class="token comment">// [tl! remove]</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Facades<span class="token punctuation">\</span>App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Publisher</span><span class="token punctuation">;</span> <span class="token comment">// [tl! add]</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Database<span class="token punctuation">\</span>Eloquent<span class="token punctuation">\</span>Model</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">class</span> <span class="token class-name-definition class-name">Podcast</span> <span class="token keyword">extends</span> <span class="token class-name">Model</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token doc-comment comment">/**</span>
<span class="line">         * 发布播客。</span>
<span class="line">         */</span></span>
<span class="line">        <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">publish</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Publisher</span> <span class="token variable">$publisher</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span> <span class="token comment">// [tl! remove]</span></span>
<span class="line">        <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">publish</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span> <span class="token comment">// [tl! add]</span></span>
<span class="line">        <span class="token punctuation">{</span></span>
<span class="line">            <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'publishing'</span> <span class="token operator">=></span> <span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">            <span class="token variable">$publisher</span><span class="token operator">-></span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [tl! remove]</span></span>
<span class="line">            <span class="token class-name static-context">Publisher</span><span class="token operator">::</span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [tl! add]</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当使用实时 Facade 时，Publisher 的实现将从服务容器中解析出来，解析的依据是接口或类名中出现在 <code v-pre>Facades</code> 前缀之后的部分。在测试时，可以使用 Laravel 内置的 Facade 测试辅助函数来模拟这个方法调用：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token comment">// Pest</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Podcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Facades<span class="token punctuation">\</span>App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Publisher</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Testing<span class="token punctuation">\</span>RefreshDatabase</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">uses</span><span class="token punctuation">(</span><span class="token class-name static-context">RefreshDatabase</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token function">test</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'podcast can be published'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$podcast</span> <span class="token operator">=</span> <span class="token class-name static-context">Podcast</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token class-name static-context">Publisher</span><span class="token operator">::</span><span class="token function">shouldReceive</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'publish'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">once</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token variable">$podcast</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token variable">$podcast</span><span class="token operator">-></span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"><span class="token comment">// PHPUnit</span></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">Tests<span class="token punctuation">\</span>Feature</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Models<span class="token punctuation">\</span>Podcast</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Facades<span class="token punctuation">\</span>App<span class="token punctuation">\</span>Contracts<span class="token punctuation">\</span>Publisher</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Testing<span class="token punctuation">\</span>RefreshDatabase</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Tests<span class="token punctuation">\</span>TestCase</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">PodcastTest</span> <span class="token keyword">extends</span> <span class="token class-name">TestCase</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">use</span> <span class="token package">RefreshDatabase</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 测试例子</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">test_podcast_can_be_published</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token variable">$podcast</span> <span class="token operator">=</span> <span class="token class-name static-context">Podcast</span><span class="token operator">::</span><span class="token function">factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token class-name static-context">Publisher</span><span class="token operator">::</span><span class="token function">shouldReceive</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'publish'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">once</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">with</span><span class="token punctuation">(</span><span class="token variable">$podcast</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token variable">$podcast</span><span class="token operator">-></span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="facade-类引用" tabindex="-1"><a class="header-anchor" href="#facade-类引用"><span>Facade 类引用</span></a></h2>
<p>下面表格列出每个 Facade 及其底层类, 可以快速查阅给定 Facade 根目录的 API 文档, 还包含了 <a href="https://yiyan.baidu.com/docs/laravel/11.x/container" target="_blank" rel="noopener noreferrer">服务容器绑定</a> 的键名称(key)。</p>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/11.x/facadesmd/16656" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/fa...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/11.x/facadesmd/16656" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/11.x/fa...</a></p>
</blockquote>
</div></template>


